package com.xb.system.listener;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xb.model.domain.CompanyData;
import com.xb.model.domain.CompanyDataOutput;
import com.xb.model.domain.entity.FileUpload;
import com.xb.model.domain.entity.VipPackage;
import com.xb.system.mapper.db1.FileUploadMapper;
import com.xb.system.mapper.db1.VipPackageMapper;
import com.xb.system.service.UsersService;
import lombok.extern.slf4j.Slf4j;


import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j
public class ExcelDataThreadPoolListener extends AnalysisEventListener<CompanyData> {

    private final ExecutorService executorService = Executors.newFixedThreadPool(10);
    private final List<CompanyData> batchList = new CopyOnWriteArrayList<>();
    private final List<CompanyDataOutput> allOutputList = Collections.synchronizedList(new ArrayList<>());
    private final UsersService userService;
    private final ExcelWriter excelWriter;
    private final WriteSheet writeSheet;
    private final FileUploadMapper fileUploadMapper;
    private final VipPackageMapper vipPackageMapper;
    private final Long fileUploadId;
    private final int BATCH_SIZE = 10000; // 每10000条数据一个批次
    private final int PARALLEL_BATCHES = 10; // 10个线程并行查询，每个线程1000条数据
    private final AtomicInteger validPhoneCount = new AtomicInteger(0);
    
    // 用于去重的Set，存储"企业名称+法定代表人+电话"的组合
    private final Set<String> processedRecords = Collections.synchronizedSet(new HashSet<>());

    // 构造函数保持不变
    public ExcelDataThreadPoolListener(UsersService userService, String outputFilePath, FileUploadMapper fileUploadMapper,
                                       VipPackageMapper vipPackageMapper, Long fileUploadId) {
        this.userService = userService;
        this.fileUploadMapper = fileUploadMapper;
        this.vipPackageMapper = vipPackageMapper;
        this.fileUploadId = fileUploadId;

        File outputDir = new File(new File(outputFilePath).getParent());
        if (!outputDir.exists()) {
            boolean created = outputDir.mkdirs();
            if (!created) {
                throw new RuntimeException("无法创建输出目录：" + outputDir.getAbsolutePath());
            }
        }

        if (!outputDir.canWrite()) {
            throw new RuntimeException("没有写入权限：" + outputDir.getAbsolutePath());
        }

        try {
            this.excelWriter = EasyExcel.write(outputFilePath, CompanyDataOutput.class).build();
        } catch (Exception e) {
            throw new RuntimeException("创建 ExcelWriter 失败", e);
        }
        this.writeSheet = EasyExcel.writerSheet("Sheet1").build();
    }

    @Override
    public void invoke(CompanyData companyData, AnalysisContext context) {
        log.info("读取到数据: phone={}, morePhones={}, representative={}, companyName={}", 
                companyData.getPhone(), companyData.getMorePhones(), companyData.getRepresentative(), companyData.getCompanyName());
        
        // 如果 phone 为空，设置为 "无"，保持原有逻辑
        if (companyData.getPhone() == null || companyData.getPhone().trim().isEmpty()) {
            companyData.setPhone("无");
        }
        batchList.add(companyData);
        log.debug("当前批次数据量: {}", batchList.size());
        
        if (batchList.size() >= BATCH_SIZE) {
            log.info("达到批次大小{}，开始处理", BATCH_SIZE);
            processCurrentBatch();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("Excel读取完成，开始处理剩余数据，批次数据量: {}", batchList.size());
        if (!batchList.isEmpty()) {
            processCurrentBatch();
        }
        shutdownExecutorService();
        writeResultsToExcel();
        
        log.info("准备更新FileUpload和VipPackage，当前validPhoneCount: {}", validPhoneCount.get());
        updateFileUploadAndVipPackage();
        log.info("FileUpload和VipPackage更新完成");
    }

    private void shutdownExecutorService() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(10, TimeUnit.MINUTES)) {
                log.warn("线程池未能在规定时间内关闭，强制关闭");
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("线程池关闭被中断", e);
        }
    }

    private void writeResultsToExcel() {
        try {
            log.info("准备写入结果文件，数据量：{}", allOutputList.size());
            log.info("validPhoneCount: {}, allOutputList.size(): {}", validPhoneCount.get(), allOutputList.size());
            if (!allOutputList.isEmpty()) {
                excelWriter.write(allOutputList, writeSheet);
            } else {
                log.warn("没有有效的输出数据，生成空文件");
                excelWriter.write(Collections.singletonList(new CompanyDataOutput()), writeSheet);
            }
        } catch (Exception e) {
            log.error("写入结果文件失败", e);
            throw new RuntimeException("写入结果文件失败", e);
        } finally {
            try {
                excelWriter.finish();
                log.info("结果文件写入完成，路径：{}", fileUploadMapper.selectById(fileUploadId).getResultFilePath());
            } catch (Exception e) {
                log.error("关闭 ExcelWriter 失败", e);
            }
        }
    }

    private void updateFileUploadAndVipPackage() {
        try {
            FileUpload fileUpload = fileUploadMapper.selectById(fileUploadId);
            log.info("更新前 - fileUploadId: {}, 当前totalCount: {}, validPhoneCount: {}", 
                    fileUploadId, fileUpload.getTotalCount(), validPhoneCount.get());
            
            fileUpload.setTotalCount(validPhoneCount.get());
            fileUploadMapper.updateById(fileUpload);
            
            log.info("更新后 - fileUploadId: {}, 新totalCount: {}, validPhoneCount: {}", 
                    fileUploadId, fileUpload.getTotalCount(), validPhoneCount.get());

            VipPackage vipPackage = vipPackageMapper.selectOne(new QueryWrapper<VipPackage>()
                    .eq("user_id", fileUpload.getUserId()).eq("is_deleted", 0));
            if (vipPackage != null) {
                vipPackage.setUsedQuota(vipPackage.getUsedQuota() + validPhoneCount.get());
                vipPackageMapper.updateById(vipPackage);
                log.info("更新VipPackage - userId: {}, 新增quota: {}, 总quota: {}", 
                        fileUpload.getUserId(), validPhoneCount.get(), vipPackage.getUsedQuota());
            }
        } catch (Exception e) {
            log.error("更新 FileUpload 或 VipPackage 失败", e);
        }
    }

    private void processCurrentBatch() {
        List<CompanyData> batchToProcess = new ArrayList<>(batchList);
        batchList.clear();
        log.info("开始处理批次，数据量: {}", batchToProcess.size());
        processBatch(batchToProcess);
    }

    private void processBatch(List<CompanyData> batchToProcess) {
        // 机制二：将1000条数据分成10个批次并行处理
        List<List<CompanyData>> subBatches = splitIntoSubBatches(batchToProcess, PARALLEL_BATCHES);
        
        List<CompanyDataOutput> outputList = Collections.synchronizedList(new ArrayList<>());
        
        // 等待所有子批次完成（不关闭线程池，让doAfterAllAnalysed统一管理）
        try {
            // 使用CountDownLatch等待所有任务完成
            java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(subBatches.size());
            
            // 并行处理10个子批次
            for (List<CompanyData> subBatch : subBatches) {
                executorService.submit(() -> {
                    try {
                        processSubBatch(subBatch, outputList);
                    } catch (Exception e) {
                        log.error("处理子批次失败", e);
                    } finally {
                        latch.countDown();
                    }
                });
            }
            
            // 等待所有子批次完成
            latch.await(30, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("子批次处理被中断", e);
        }
        
        allOutputList.addAll(outputList);
    }
    
    /**
     * 将批次数据分成多个子批次
     */
    private List<List<CompanyData>> splitIntoSubBatches(List<CompanyData> batch, int subBatchCount) {
        List<List<CompanyData>> subBatches = new ArrayList<>();
        int subBatchSize = Math.max(1, batch.size() / subBatchCount);
        
        for (int i = 0; i < subBatchCount; i++) {
            int startIndex = i * subBatchSize;
            int endIndex = (i == subBatchCount - 1) ? batch.size() : Math.min(startIndex + subBatchSize, batch.size());
            
            if (startIndex < batch.size()) {
                List<CompanyData> subBatch = new ArrayList<>(batch.subList(startIndex, endIndex));
                subBatches.add(subBatch);
                log.debug("创建子批次 {}: 数据量 {}", i + 1, subBatch.size());
            }
        }
        
        return subBatches;
    }
    
    /**
     * 处理子批次数据 - 1000条数据并行查询
     * 不是1000个子线程，而是1000条数据同时进行数据库查询
     */
    private void processSubBatch(List<CompanyData> subBatch, List<CompanyDataOutput> outputList) {
        log.info("开始处理子批次，数据量: {}", subBatch.size());
        
        // 1000条数据并行查询：使用固定线程池控制并发度
        java.util.concurrent.ExecutorService internalExecutor = java.util.concurrent.Executors.newFixedThreadPool(50);
        java.util.concurrent.CountDownLatch internalLatch = new java.util.concurrent.CountDownLatch(subBatch.size());
        
        for (CompanyData companyData : subBatch) {
            internalExecutor.submit(() -> {
                try {
                    log.debug("并行查询数据: phone={}, representative={}", 
                            companyData.getPhone(), companyData.getRepresentative());
                    processCompanyData(companyData, outputList);
                } catch (Exception e) {
                    log.error("处理 CompanyData 失败: {}", companyData, e);
                    // 即使某一行失败，也继续处理其他行
                    CompanyDataOutput errorResult = new CompanyDataOutput();
                    errorResult.setPhone(companyData.getPhone());
                    errorResult.setCompanyName(companyData.getCompanyName());
                    errorResult.setRepresentative(companyData.getRepresentative());
                    errorResult.setNote1(companyData.getNote1());
                    errorResult.setNote2(companyData.getNote2());
                    errorResult.setNote3(companyData.getNote3());
                    errorResult.setMatchResult(0); // 默认不匹配
                    outputList.add(errorResult);
                } finally {
                    internalLatch.countDown();
                }
            });
        }
        
        try {
            // 等待所有1000条数据并行查询完成
            internalLatch.await(10, java.util.concurrent.TimeUnit.MINUTES);
            log.info("子批次并行查询完成，处理了{}条数据，输出{}条结果", subBatch.size(), outputList.size());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("子批次并行查询被中断", e);
        } finally {
            internalExecutor.shutdown();
        }
    }
    
    private void processCompanyData(CompanyData companyData, List<CompanyDataOutput> outputList) {
        log.debug("处理公司数据: phone={}, morePhones={}, representative={}", 
                companyData.getPhone(), companyData.getMorePhones(), companyData.getRepresentative());
        
        // 修改点1：将 phone 字段按分隔符拆分，统一处理多个号码
        String[] phones = companyData.getPhone().trim().split("[,，;/\\s]");
        log.debug("解析phone字段得到{}个号码: {}", phones.length, java.util.Arrays.toString(phones));
        processPhones(companyData, phones, outputList);

        // 处理 morePhones 字段，保持原有逻辑
        if (companyData.getMorePhones() != null && !companyData.getMorePhones().trim().isEmpty()) {
            String[] morePhones = companyData.getMorePhones().split("[,，;/\\s]");
            log.debug("解析morePhones字段得到{}个号码: {}", morePhones.length, java.util.Arrays.toString(morePhones));
            processPhones(companyData, morePhones, outputList);
        }
    }

    private void processPhones(CompanyData companyData, String[] phones, List<CompanyDataOutput> outputList) {
        log.debug("开始处理{}个号码", phones.length);
        for (String phone : phones) {
            // 清理电话号码：去除空格和特殊字符
            if (phone != null) {
                phone = phone.trim();
            }
            
            log.debug("处理号码: '{}'", phone);
            
            // 跳过空值或无效号码
            if (phone == null || phone.isEmpty() || phone.equals("-") || phone.equals("无")) {
                log.debug("跳过空值或无效号码: '{}'", phone);
                continue;
            }
            
            // 更宽松的号码验证：支持手机号、座机号、带区号的号码
            if (!isValidPhoneNumber(phone)) {
                log.debug("跳过无效号码: '{}'", phone);
                continue;
            }
            
            log.debug("号码'{}'验证通过，开始匹配", phone);
            try {
                // 生成去重键：企业名称+法定代表人+电话
                String dedupKey = generateDedupKey(companyData.getCompanyName(), companyData.getRepresentative(), phone);
                
                // 检查是否已处理过相同的记录
                if (processedRecords.contains(dedupKey)) {
                    log.debug("跳过重复记录: {}", dedupKey);
                    continue;
                }
                
                // 标记为已处理
                processedRecords.add(dedupKey);
                
                boolean matchFound = userService.checkUserMatch(phone, companyData.getRepresentative());
                CompanyDataOutput result = new CompanyDataOutput();
                result.setPhone(phone);
                result.setCompanyName(companyData.getCompanyName() != null ? companyData.getCompanyName() : "");
                result.setRepresentative(companyData.getRepresentative() != null ? companyData.getRepresentative() : "");
                result.setNote1(companyData.getNote1());
                result.setNote2(companyData.getNote2());
                result.setNote3(companyData.getNote3());
                result.setMatchResult(matchFound ? 1 : 0);
                outputList.add(result);
                validPhoneCount.incrementAndGet(); // 只有通过去重检查的号码才计数
                log.info("处理电话：phone={}, representative={}, matchResult={}", phone, companyData.getRepresentative(), matchFound ? 1 : 0);
            } catch (Exception e) {
                log.error("处理电话失败: phone={}, representative={}", phone, companyData.getRepresentative(), e);
                
                // 生成去重键：企业名称+法定代表人+电话
                String dedupKey = generateDedupKey(companyData.getCompanyName(), companyData.getRepresentative(), phone);
                
                // 检查是否已处理过相同的记录
                if (processedRecords.contains(dedupKey)) {
                    log.debug("跳过重复记录（异常处理）: {}", dedupKey);
                    continue;
                }
                
                // 标记为已处理
                processedRecords.add(dedupKey);
                
                CompanyDataOutput result = new CompanyDataOutput();
                result.setPhone(phone);
                result.setCompanyName(companyData.getCompanyName() != null ? companyData.getCompanyName() : "");
                result.setRepresentative(companyData.getRepresentative() != null ? companyData.getRepresentative() : "");
                result.setNote1(companyData.getNote1());
                result.setNote2(companyData.getNote2());
                result.setNote3(companyData.getNote3());
                result.setMatchResult(0);
                outputList.add(result);
                validPhoneCount.incrementAndGet(); // 只有通过去重检查的号码才计数
            }
        }
    }

    public int getValidPhoneCount() {
        return validPhoneCount.get();
    }
    
    /**
     * 生成去重键：企业名称+法定代表人+电话
     */
    private String generateDedupKey(String companyName, String representative, String phone) {
        String safeCompanyName = companyName != null ? companyName.trim() : "";
        String safeRepresentative = representative != null ? representative.trim() : "";
        String safePhone = phone != null ? phone.trim() : "";
        
        return safeCompanyName + "|" + safeRepresentative + "|" + safePhone;
    }

    /**
     * 验证电话号码是否有效
     * 只支持中国手机号码（11位，以1开头，第二位是3-9）
     */
    private boolean isValidPhoneNumber(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        
        String trimmedPhone = phone.trim();
        
        // 跳过明显的无效标记
        if (trimmedPhone.equals("-") || trimmedPhone.equals("无") || trimmedPhone.equals("无")) {
            return false;
        }
        
        // 去除非数字字符，保留数字
        String cleanPhone = trimmedPhone.replaceAll("[^\\d]", "");
        
        // 只验证中国手机号：11位，以1开头，第二位是3-9
        if (cleanPhone.matches("^1[3-9]\\d{9}$")) {
            return true;
        }
        
        return false;
    }
}